package com.wuyan.web.base.helper;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wuyan.web.base.helper.auth.LoginInfo;
import com.wuyan.web.base.helper.rep.RepBody;
import com.wuyan.web.base.helper.rep.RepCodeEnum;
import com.wuyan.web.base.helper.req.WuyanWebAuthApi;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import java.util.*;

@Component
@Slf4j
public class BaseApi {
    private static final String SESSION_AUTH_LOGIN_NAME = "auth-login";

    /**
     * 缓存默认的有效期：20分钟
     */
    private static final long DEFAULT_CACHE_TIMEOUT = 20 * 60L;

    @Autowired
    private SpringRedisHelper springRedisHelper;

    @Autowired
    private WuyanWebAuthApi wuyanWebAuthApi;

    @Autowired
    private ObjectMapper mapper;

    /**
     * 获取授权账户信息
     *
     * @param request 请求体
     * @return LoginInfo
     */
    public LoginInfo getLoginInfo(HttpServletRequest request) {
        return getLoginInfo(getAccessToken(request), request.getSession());
    }

    /**
     * 根据token获取账户信息
     *
     * @param token 授权码
     * @return LoginInfo
     */
    public LoginInfo getLoginInfo(String token, HttpSession session){
        String loginInfoStr = (String) session.getAttribute(SESSION_AUTH_LOGIN_NAME);
        if (null != loginInfoStr) {
            try {
                return mapper.readValue(loginInfoStr, LoginInfo.class);
            } catch (JsonProcessingException e) {
                return null;
            }
        }

        if (StringUtils.isBlank(token)) {
            return null;
        }

        RepBody<LoginInfo> res = wuyanWebAuthApi.check(token);

        if (null == res || res.getCode() != RepCodeEnum.OK.getCode()) {
            return null;
        }

        return res.getData();
    }

    /**
     * 设置缓存信息
     *
     * @param request 请求体
     * @param key     键
     * @param value   值
     * @return boolean
     */
    public boolean setAttr(HttpServletRequest request, String key, Object value) {
        return setAttr(request, key, value, DEFAULT_CACHE_TIMEOUT);
    }

    /**
     * 更新缓存信息，可指定有效时长
     *
     * @param request 请求体
     * @param key     键
     * @param value   值
     * @param timeout 过期时间
     * @return boolean
     */
    public boolean setAttr(HttpServletRequest request, String key, Object value, long timeout) {
        request.getSession().setAttribute(key, value);
        return springRedisHelper.set(key, value, timeout);
    }

    /**
     * 从缓存中读取
     *
     * @param request 请求体
     * @param key     键
     * @param tClass  期望返回的数据类型
     * @param remove  是否读取完后移除
     * @return T
     */
    public <T> T getAttr(HttpServletRequest request, String key, Class<T> tClass, boolean remove) {
        T value = tClass.cast(request.getSession().getAttribute(key));

        if (value == null) {
            value = springRedisHelper.get(key, tClass);
        }

        if (remove) {
            request.getSession().removeAttribute(key);
            springRedisHelper.remove(key);
        }

        return value;
    }

    /**
     * 获取授权码
     *
     * @param request 请求体
     * @return String
     */
    public String getAccessToken(HttpServletRequest request) {
        HttpSession session = request.getSession();
        String ak = (String) session.getAttribute("authorization");
        if (StringUtils.isBlank(ak)) {
            ak = (String) session.getAttribute("Authorization");
        }

        // 请求头中获取
        if (StringUtils.isBlank(ak)) {
            ak = request.getHeader("authorization");
        }
        // 请求头中获取
        if (StringUtils.isBlank(ak)) {
            ak = request.getHeader("Authorization");
        }

        // 请求路径中获取
        if (StringUtils.isBlank(ak)) {
            ak = request.getParameter("key");
        }
        if (StringUtils.isBlank(ak)) {
            ak = request.getParameter("key");
        }

        return ak == null ? ak : ak.trim();
    }

    /**
     * 获取请求参数
     *
     * @param request 请求体
     * @param key     键名
     * @param tClass  期望返回的数据类型
     * @param isStr   是否转为字符串拼接.
     * @return T
     */
    public <T> T getParam(HttpServletRequest request, String key, Class<T> tClass, boolean isStr) {
        Map<String, String[]> params = request.getParameterMap();

        T res = null;
        if (params.containsKey(key)) {
            if (isStr) {
                StringBuilder r = new StringBuilder();
                String[] param = params.get(key);
                int index = param.length;

                for (String value : param) {
                    if (index == 1) {
                        r.append(value);
                    } else {
                        r.append(value).append(",");
                    }
                    index--;
                }

                res = tClass.cast(r.toString());
            } else {
                res = tClass.cast(params.get(key));
            }
        }

        return res;
    }
}
